#include "global.h"
#include "service/include/port/swei_log.h"
#include "service/include/port/swei_fw_info.h"
#include "service/include/port/swei_wrapper.h"
#include "comm/co_heartbeat.h"
// #include "service/include/swei_protocol.h"
// #include "service/include/swei_package.h"
#include "public/errno.h"

#include "mmgr/include/mmgr_modem.h"
#include "mmgr/include/mmgr_misc.h"
#include "misc/misc_api.h"

void _imei_str_to_bcd(uint8_t imei_buf[], uint8_t bcd_buf[]);
int32_t swei_get_device_imei_bcd(uint8_t *p_get_imei);
int32_t swei_get_device_imei(uint8_t *p_get_imei);
int32_t swei_get_iccid(uint8_t *p_get_iccid);
int32_t swei_get_sn(uint8_t *p_get_sn);
int32_t swei_get_libat(void *p_get_libat, uint32_t size);
int32_t swei_get_libat_charger(void *p_get_data, uint32_t size);
extern uint16_t emu_info2_get(uint8_t *p_data, uint16_t len);
extern uint16_t econ_stat_info3_get(uint8_t *p_data, uint16_t len);
extern uint16_t econ_stat_info1_get(uint8_t *p_data, uint16_t len);
extern uint16_t econ_seqnum_get(uint8_t *p_data, uint16_t len);
extern uint16_t econ_version_get(uint8_t *p_data, uint16_t len);
extern uint16_t emu_eppr_vr_get(uint8_t *p_data, uint16_t len);
extern uint16_t bike_system_info_get(uint8_t *p_data, uint16_t len);
static int32_t swei_get_battery_info(void *p_get_data);
static int32_t swei_get_chg_stat(void *p_get_data);
static int32_t swei_get_econ_info(void *p_get_data);
static int32_t swei_get_econ_stat(void *p_get_data);
static int32_t swei_get_econ_basic_info(void *p_get_data);
static int32_t swei_get_bike_data1(void *p_get_data);
static int32_t swei_get_bike_data2(void *p_get_data);
static int32_t swei_get_bike_stat(void *p_get_data);
static int32_t swei_get_fault_code(void *p_get_data);
static int32_t swei_get_signal_quality(void *p_get_data);

/*****************************************************************************
 * Function      : swei_get_device_info
 * Description   : 获取tbox设备的相关静态信息
 * Input         : uint8_t type  @ref set_get_device_info_enum
                   uint8_t *p_get_info
 * Output        : None
 * Return        :
 * Others        :
 * Record
 * 1.Date        : 20230725
 *   Author      : yanfeng
 *   Modification: Created function

*****************************************************************************/
int32_t swei_get_device_info(device_info_e type, void *p_get_info, uint32_t get_info_size)
{
    if (NULL == p_get_info)
    {
        log_e("p_get_info null");
        return -EPERM;
    }

    switch (type)
    {
        case IMEI_INFO_BCD:
            return swei_get_device_imei_bcd(p_get_info);
            break;

        case ICCID_INFO:
            return swei_get_iccid(p_get_info);
            break;

        case SN_INFO:
            return swei_get_sn(p_get_info);
            break;

        case IMEI_INFO:
            return swei_get_device_imei(p_get_info);
            break;

        case LIBAT_INFO:
            return swei_get_libat(p_get_info, get_info_size);
            break;
        
        case LIBAT_CHARGER_INFO:
            return swei_get_libat_charger(p_get_info, get_info_size);
            break;

        case SINAL_QUALITY:
            return swei_get_signal_quality(p_get_info);
            break;

        /* Tbox电池信息（0x1010) */
        case BATT_INFO:
            return swei_get_battery_info(p_get_info);
            break;

        /* Tbox电池充电事件信息（0x1011） */
        case CHG_STAT:
            return swei_get_chg_stat(p_get_info);
            break;

        /* 电控状态信息（0x2001） */
        case ECON_INFO:
            return swei_get_econ_info(p_get_info);
            break;

        /* 电控运行信息（0x2002 ） */
        case ECON_STAT:
            return swei_get_econ_stat(p_get_info);
            break;

        /* 电控基本信息（0x2003）*/
        case ECON_BASIC_INFO:
            return swei_get_econ_basic_info(p_get_info);
            break;
        
        /* 车况数据1（0x3001）*/
        case BIKE_DATA1:
            return swei_get_bike_data1(p_get_info);
            break;

        /* 车况数据2（0x3002）*/
        case BIKE_DATA2:
            return swei_get_bike_data2(p_get_info);
            break;

        /* 车辆状态（0x3003）*/
        case BIKE_STAT:
            return swei_get_bike_stat(p_get_info);
            break;

        /* 故障码（0x4001） */
        case FAULT_CODE:
            return swei_get_fault_code(p_get_info);
            break;       

        default:
            log_e("get device tpye err, type:%d", type);
            return -EPERM;
    }
}


/// @brief IMEI BCD格式转化
/// @param imei_buf
/// @param bcd_buf
void _imei_str_to_bcd(uint8_t imei_buf[], uint8_t bcd_buf[])
{
    /* add '0' to the beginning of the 15-digit IMEI*/
    bcd_buf[0] = (uint8_t)(0x0 << 4) + (imei_buf[0] - '0');
    bcd_buf[1] = (uint8_t)((imei_buf[1] - '0') << 4) + (imei_buf[2] - '0');
    bcd_buf[2] = (uint8_t)((imei_buf[3] - '0') << 4) + (imei_buf[4] - '0');
    bcd_buf[3] = (uint8_t)((imei_buf[5] - '0') << 4) + (imei_buf[6] - '0');

    bcd_buf[4] = (uint8_t)((imei_buf[7] - '0') << 4) + (imei_buf[8] - '0');
    bcd_buf[5] = (uint8_t)((imei_buf[9] - '0') << 4) + (imei_buf[10] - '0');
    bcd_buf[6] = (uint8_t)((imei_buf[11] - '0') << 4) + (imei_buf[12] - '0');
    bcd_buf[7] = (uint8_t)((imei_buf[13] - '0') << 4) + (imei_buf[14] - '0');
}


// #define USE_TEST_PARAM (1)

/// @brief 获取设备IMEI BCD格式
/// @param p_get_imei
/// @return
int32_t swei_get_device_imei_bcd(uint8_t *p_get_imei)
{
    uint8_t imei_bcd[8] = {0};

    /* 获取imie时统一用BCD码返回    */
    if (NULL == p_get_imei)
    {
        log_e("p_get_imei null");
        return -EPERM;
    }

#ifdef USE_TEST_PARAM
    _imei_str_to_bcd((uint8_t *)"861684052504668", imei_bcd); 
#else
    _imei_str_to_bcd((uint8_t *)mmgr_imei_get(), imei_bcd);   
#endif
    memcpy(p_get_imei, &imei_bcd[0], IMEI_BCD_LEN);

    return 0; // SUCCESS;
}

/**
 * @brief 
 * @param  p_get_iccid      My Param doc
 * @return int32_t 
 */
int32_t swei_get_iccid(uint8_t *p_get_iccid)
{
    if(p_get_iccid)
#ifdef USE_TEST_PARAM    
        strcpy((char *)p_get_iccid, "89860404192290027957"); 
#else    
        strcpy((char *)p_get_iccid, mmgr_iccid_get()); 
#endif        

    return 0;
}

/**
 * @brief 
 * @param  p_get_sn         My Param doc
 * @return int32_t 
 */
int32_t swei_get_sn(uint8_t *p_get_sn)
{
    char temp[32] = {0};

    tbox_get_sn(temp, sizeof(temp));
    if(strlen(temp) <= 0)
    {
        return -ECONFIG;
    }

#ifdef USE_TEST_PARAM        
    if(p_get_sn)
        strcpy((char *)p_get_sn, "DA35D1C10F2408220002"); 
#else
    if(p_get_sn && strlen(temp)) 
        strcpy((char *)p_get_sn, temp);
#endif

    return 0;
}

#include "lettershell/shell.h"
void testcase_for_sailvan_fw_api(void)
{
    char sn[21] = {0};

    swei_get_sn((uint8_t *)sn);
    log_d("swei_get_sn ret sn :%s\r\n", sn);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
                 sailvan_tst, testcase_for_sailvan_fw_api, testcase for sailvan fw api);

/// @brief 获取设备IMEI string格式
/// @param p_get_imei
/// @return
int32_t swei_get_device_imei(uint8_t *p_get_imei)
{
    /* 获取imie时统一用BCD码返回    */
    if (NULL == p_get_imei)
    {
        log_e("p_get_imei null");
        return -EPERM;
    }

#ifdef USE_TEST_PARAM    
    snprintf((char *)p_get_imei, IMEI_LEN, "%s", "861684052504668"); // 861684052504668
#else    
    snprintf((char *)p_get_imei, IMEI_LEN, "%s", mmgr_imei_get()); 
#endif    
    return 0; // SUCCESS;
}

/**
 * @brief 获取小电池信息
 * @todo   待实现
 * @param  p_get_data       My Param doc
 * @param  size             My Param doc
 * @return int32_t 
 */
int32_t swei_get_libat(void *p_get_data, uint32_t size)
{
    libat_info_t *bat = (libat_info_t *)p_get_data;

    if(NULL == bat)
    {
        return -EPERM;
    }

    /* 1. 通过misc的devsta更新结构体内容 */

    return 0;
}

/**
 * @brief 获取充电桩状态;
 * @todo   待实现
 * @param  p_get_data       My Param doc
 * @param  size             My Param doc
 * @return int32_t 
 */
int32_t swei_get_libat_charger(void *p_get_data, uint32_t size)
{
    libat_charger_info_t *bat = (libat_charger_info_t *)p_get_data;

    if(NULL == bat)
    {
        return -EPERM;
    }

    /* 1. 通过misc的devsta更新结构体内容 */

    return 0;
}


static int32_t swei_get_signal_quality(void *p_get_data)
{
    signal_quality_t *signal_quality = (signal_quality_t *)p_get_data;
    int32_t csq = 0;
    int32_t rsrp = 0;

    if(NULL == signal_quality)
    {
        return -EPERM;
    }

    modem_get_signal_quality(&csq, &rsrp);
    log_d("Get csq:%d, rsrp:%d\r\n", csq, rsrp);
    signal_quality->csq = (uint8_t)(csq);
    signal_quality->rsrp = (uint8_t)(abs(rsrp));

    return 0;
}


int32_t swei_get_battery_info(void *p_get_data)
{
    batt_info_t *batt_info = (batt_info_t *)p_get_data;
    li_batt_status_info_t li_batt_status_info = {0};

    lbatt_status_info_get((uint8_t *)&li_batt_status_info, sizeof(li_batt_status_info));
    
    if(NULL == batt_info)
    {
        return -EPERM;
    }

    batt_info->volt = li_batt_status_info.batt_voltage;
    /* 电量比例 */
    batt_info->volt_percent = li_batt_status_info.soc;

    return 0;
}


static int32_t swei_get_chg_stat(void *p_get_data)
{
    libat_charger_info_t *chg_status = (libat_charger_info_t *)p_get_data;
    lbatt_chg_stat_t lbatt_chg_stat = {0};
    
    if(NULL == chg_status)
    {
        return -EPERM;
    }

    lbatt_chg_stat_get((uint8_t *)&lbatt_chg_stat, sizeof(lbatt_chg_stat));
    chg_status->charge_count = lbatt_chg_stat.total_chg_cnt;
    chg_status->charge_total_time = lbatt_chg_stat.total_chg_time;

    return 0;
}


static int32_t swei_get_econ_info(void *p_get_data)
{
    econ_info_t *econ_info = (econ_info_t *)p_get_data;
    econ_info1_t econ_stat_info1 = {0};
    econ_info2_t econ_stat_info2 = {0};
    co_motor_ctrl_info_1_t co_motor_ctrl_info = {0};

    if(NULL == econ_info)
    {
        return -EPERM;
    }

    emu_info1_get((uint8_t *)&co_motor_ctrl_info, sizeof(co_motor_ctrl_info));
    if (co_motor_ctrl_info.speed_valid)
        econ_info->speed = (uint16_t)co_motor_ctrl_info.speed * 100;  //econ_info->speed单位 0.01km/s
    else 
        econ_info->speed = 0xffff;
    if (co_motor_ctrl_info.motor_temp_valid)
        econ_info->temp = (uint16_t)(co_motor_ctrl_info.motor_temp * 10);
    else
        econ_info->temp = 0xffff;

    econ_stat_info1_get((uint8_t *)&econ_stat_info1, sizeof(econ_stat_info1));
    econ_info->torque_volt = econ_stat_info1.volt_output;
    econ_info->motor_speed = econ_stat_info1.motor_speed;
    econ_info->ride_freq = econ_stat_info1.ride_freq;
    econ_info->braking_stat = econ_stat_info1.braking_stat;

    econ_stat_info2_get((uint8_t *)&econ_stat_info2, sizeof(econ_stat_info2));
    econ_info->bus_volt = (uint16_t)(econ_stat_info2.bus_volt * 10);
    econ_info->bus_cur = (uint16_t)(econ_stat_info2.bus_cur * 10);
    econ_info->throttle_volt = (uint8_t)(econ_stat_info2.throttle_volt * 10);

    return 0;
}


static int32_t swei_get_econ_stat(void *p_get_data)
{
    econ_stat_t *econ_stat = (econ_stat_t *)p_get_data;
    electric_vehicle_info2_t electric_vehicle_info2 = {0};
    econ_info1_t econ_stat_info1 = {0};
    econ_info3_t econ_stat_info3 = {0};

    if(NULL == econ_stat)
    {
        return -EPERM;
    }

    emu_info2_get((uint8_t *)&electric_vehicle_info2, sizeof(electric_vehicle_info2));
    if (electric_vehicle_info2.pwr_lvl_is_valid)
        econ_stat->pwr_lvl = electric_vehicle_info2.pwr_lvl;

    econ_stat_info3_get((uint8_t *)&econ_stat_info3, sizeof(econ_stat_info3));
    econ_stat->econ_work_stat = econ_stat_info3.econ_work_stat;
    econ_stat->econ_mode = econ_stat_info3.econ_mode;

    econ_stat_info1_get((uint8_t *)&econ_stat_info1, sizeof(econ_stat_info1));    
    econ_stat->vehicle_stat = econ_stat_info1.motor_stat;

    return 0;
}


static int32_t swei_get_econ_basic_info(void *p_get_data)
{
    econ_basic_info_t *econ_basic_info = (econ_basic_info_t *)p_get_data;
    version_t econ_version = {0};
    bike_system_info_t bike_system_info = {0};

    if(NULL == econ_basic_info)
    {
        return -EPERM;
    }

    /* 序列号 */
    econ_seqnum_get((uint8_t *)econ_basic_info->sn, sizeof(econ_basic_info->sn));
    econ_basic_info->sn_len = strlen(econ_basic_info->sn);

    /* 软硬件版本 */
    econ_version_get((uint8_t *)&econ_version, sizeof(econ_version));
    strncpy(econ_basic_info->soft_ver, econ_version.soft_version, strlen(econ_version.soft_version));   
    econ_basic_info->soft_ver_len = strlen(econ_version.soft_version); 
    strncpy(econ_basic_info->hw_ver, econ_version.hw_version, strlen(econ_version.hw_version));
    econ_basic_info->hw_ver_len = strlen(econ_version.hw_version);

    /* eeprom */
    emu_eppr_vr_get((uint8_t *)&econ_basic_info->eeprom, sizeof(econ_basic_info->eeprom));
    econ_basic_info->eeprom_len = strlen(econ_basic_info->eeprom);

    bike_system_info_get((uint8_t *)&bike_system_info, sizeof(bike_system_info));
    econ_basic_info->wheel_diameter = (uint16_t)(bike_system_info.wheel_diameter * 10);

    return 0;
}


static int32_t swei_get_bike_data1(void *p_get_data)
{
    bike_data1_t *bike_data1 = (bike_data1_t *)p_get_data;
    electric_vehicle_info2_t electric_vehicle_info2 = {0};
    batt_capacity_info_t batt_volume_info = {0};

    if(NULL == bike_data1)
    {
        return -EPERM;
    }

    emu_info2_get((uint8_t *)&electric_vehicle_info2, sizeof(electric_vehicle_info2));
    bike_data1->remain_range = (uint16_t)(electric_vehicle_info2.remain_range * 100);

    batt_capacity_info_get((uint8_t *)&batt_volume_info, sizeof(batt_volume_info));
    bike_data1->remain_volume = batt_volume_info.soc;

    return 0;
}


static int32_t swei_get_bike_data2(void *p_get_data)
{
    bike_data2_t *bike_data2 = (bike_data2_t *)p_get_data;
    electric_vehicle_info2_t electric_vehicle_info2 = {0};
    econ_info3_t econ_info3 = {0};

    if(NULL == bike_data2)
    {
        return -EPERM;
    }

    emu_info2_get((uint8_t *)&electric_vehicle_info2, sizeof(electric_vehicle_info2));
    bike_data2->single_range = (uint16_t)(electric_vehicle_info2.single_range * 100);

    econ_stat_info3_get((uint8_t *)&econ_info3 , sizeof(econ_info3));
    bike_data2->total_range = (uint32_t)(econ_info3.total_range * 100);

    return 0;
}


static int32_t swei_get_bike_stat(void *p_get_data)
{
    bike_stat_t *bike_stat = (bike_stat_t *)p_get_data;
    co_motor_ctrl_info_1_t co_motor_ctrl_info_1 = {0};
    charger_info_t charger_info = {0};
    co_status_info_t co_status_info = {0};

    if(NULL == bike_stat)
    {
        return -EPERM;
    }

    /* 骑行状态 */
    emu_info1_get((uint8_t *)&co_motor_ctrl_info_1, sizeof(co_motor_ctrl_info_1));
    if (co_motor_ctrl_info_1.speed_valid\
        && co_motor_ctrl_info_1.speed > 0)
        bike_stat->ride_stat = 1;
    else
        bike_stat->ride_stat = 0;

    /* 电子锁状态 */
    bike_stat->elock_stat = get_elock_status();

    /* 充电器连接状态 */
    charger_info_get((uint8_t *)&charger_info, sizeof(charger_info));  
    if (utils_time_is_expired(&charger_info.timer))
        bike_stat->charger_stat = false;
    else
        bike_stat->charger_stat = true;


    /* 尾灯状态 */
    co_info_get((uint8_t *)&co_status_info, sizeof(co_status_info));
    bike_stat->tailight_stat = co_status_info.tail_light;

    return 0;
}


static int32_t swei_get_fault_code(void *p_get_data)
{
    co_fault_code_t *fault_code = (co_fault_code_t *)p_get_data;

    if(NULL == fault_code)
    {
        return -EPERM;
    }

    batt_fault_info_get((uint8_t *)fault_code, sizeof(co_fault_code_t));
    fault_code ++;
    backup_batt_fault_info_get((uint8_t *)fault_code, sizeof(co_fault_code_t));
    fault_code ++;
    econ_fault_info_get((uint8_t *)fault_code, sizeof(co_fault_code_t));

    return 0;
}


/**
 * @brief 参数判断
 * @return true 
 * @return false 
 */
bool swei_config_ready(void)
{
    if(0 != swei_get_sn(NULL))
    {
        log_e("the sn not set, please call AT+WSN cmd to config the sn!!\r\n");
        return false;
    }
    
    return true;
}
